package android.slc.box.core.utils;

import cn.hutool.core.collection.CollectionUtil;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.control.ButtonBase;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.stage.Window;

import java.awt.*;
import java.util.function.Consumer;

public class ViewUtils {
    public static final int MATCH_PARENT = -1;
    public static final int WRAP_CONTENT = -2;
    private static double APP_WINDOW_MIN_WIDTH = 1138;
    private static double App_WINDOW_MIN_HEIGHT = 640;


    public static void setAppWindowMinWidth(double appWindowMinWidth) {
        APP_WINDOW_MIN_WIDTH = appWindowMinWidth;
    }

    public static void setAppWindowMinHeight(double appWindowMinHeight) {
        App_WINDOW_MIN_HEIGHT = appWindowMinHeight;
    }

    /**
     * 获取app合适的最小宽度
     *
     * @return
     */
    public static double getAppWindowMinWidth() {
        return Math.min(APP_WINDOW_MIN_WIDTH, getAppWindowMaxWidth());
    }

    /**
     * 获取app合适的最大宽度
     *
     * @return
     */
    public static double getAppWindowMinHeight() {
        return Math.min(App_WINDOW_MIN_HEIGHT, getAppWindowMaxHeight());
    }

    /**
     * 获取app窗口最大宽度
     *
     * @return
     */
    public static double getAppWindowMaxWidth() {
        GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
        //get maximum window bounds
        Rectangle maximumWindowBounds = graphicsEnvironment.getMaximumWindowBounds();
        return maximumWindowBounds.getWidth();
    }

    /**
     * 获取app窗口最大高度
     *
     * @return
     */
    public static double getAppWindowMaxHeight() {
        GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
        //get maximum window bounds
        Rectangle maximumWindowBounds = graphicsEnvironment.getMaximumWindowBounds();
        return maximumWindowBounds.getHeight();
    }

    /**
     * 获取屏幕宽度
     *
     * @return
     */
    public static double getScreenWidth() {
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        return screenSize.getWidth();
    }

    /**
     * 获取屏幕高度
     *
     * @return
     */
    public static double getScreenHeight() {
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        return screenSize.getHeight();
    }

    /**
     * 固定大小
     *
     * @param node
     * @param width
     * @param height
     */
    public static void fixedSize(Region node, double width, double height) {
        fixedWidth(node, width);
        fixedHeight(node, height);
    }

    /**
     * 固定大小
     *
     * @param node
     * @param width
     */
    public static void fixedWidth(Region node, double width) {
        node.setMinWidth(width);
        node.setMaxWidth(width);
        node.setPrefWidth(width);
    }

    /**
     * 固定大小
     *
     * @param node
     * @param height
     */
    public static void fixedHeight(Region node, double height) {
        node.setMinHeight(height);
        node.setMaxHeight(height);
        node.setPrefHeight(height);
    }

    /**
     * 失去焦点
     *
     * @param node
     */
    public static void loseFocus(Node node) {
        node.getParent().requestFocus();
        node.focusedProperty().addListener((observable, oldValue, newValue) -> {
            node.getParent().requestFocus();
        });
    }

    /**
     * 设置隐藏
     *
     * @param node
     * @param gone
     */
    @Deprecated
    public static void setGone(Node node, boolean gone) {
        setInvisible(node, gone);
        node.setManaged(!gone);
    }

    /**
     * 设置不可见
     *
     * @param node
     * @param invisible
     */
    @Deprecated
    public static void setInvisible(Node node, boolean invisible) {
        node.setVisible(!invisible);
    }

    /**
     * 设置显示
     *
     * @param node
     * @param visible
     */
    public static void setVisible(Node node, boolean visible) {
        setVisible(node, visible, visible);
    }

    /**
     * 设置显示
     *
     * @param node
     * @param visible
     */
    public static void setVisible(Node node, boolean visible, boolean managed) {
        node.setVisible(visible);
        node.setManaged(managed);
    }

    /**
     * 子节点是否全部隐藏
     *
     * @param pane
     * @return
     */
    public static boolean paneChildrenIsAllHide(Pane pane) {
        if (pane == null || pane.getChildren().isEmpty()) {
            return true;
        }
        Node visibleNode = CollectionUtil.findOne(pane.getChildren(), Node::isVisible);
        return visibleNode == null;
    }

    /**
     * 更新视图显示根据所有的子节点
     * 当所有子节点隐藏时，本节点隐藏，当有一个子节点显示时，本节点显示
     *
     * @param pane
     * @return
     */
    public static boolean updateVisibleWithAllChildrenVisible(Pane pane) {
        if (pane == null) {
            return false;
        }
        boolean paneChildrenIsAllVisible = paneChildrenIsAllHide(pane);
        pane.setVisible(!paneChildrenIsAllVisible);
        return pane.isVisible();
    }

    /**
     * 设置所有子节点的显示状态
     *
     * @param pane
     * @param visible
     */
    public static void setAllChildrenVisible(Pane pane, boolean visible) {
        if (pane == null) {
            return;
        }
        CollectionUtil.forEach(pane.getChildren(), (value, index) -> {
            value.setVisible(visible);
        });
    }

    /**
     * 移除字节点
     *
     * @param nodes
     */
    public static void removeNode(Node... nodes) {
        removeNode(true, nodes);
    }

    /**
     * 移除事件
     *
     * @param nodes
     * @param removeAction
     */
    public static void removeNode(boolean removeAction, Node... nodes) {
        if (nodes != null) {
            for (Node node : nodes) {
                if (node != null && node.getParent() != null) {
                    if (removeAction) {
                        removeAction(node);
                    }
                    Pane pane = (Pane) node.getParent();
                    pane.getChildren().remove(node);
                }
            }
        }
    }

    /**
     * 移除事件
     *
     * @param
     */
    public static void removeAction(Node... nodes) {
        if (nodes != null) {
            for (Node node : nodes) {
                if (node != null) {
                    if (node instanceof ButtonBase) {
                        ButtonBase button = (ButtonBase) node;
                        if (button.getOnAction() != null) {
                            button.setOnAction(null);
                        }
                    } else if (node instanceof javafx.scene.control.TextField) {
                        javafx.scene.control.TextField menuItem = (javafx.scene.control.TextField) node;
                        if (menuItem.getOnAction() != null) {
                            menuItem.setOnAction(null);
                        }
                    }
                }
            }
        }
    }

    /**
     * 根据父节点移除字节点所有事件
     *
     * @param panes
     */
    public static void removeActionByParent(Pane... panes) {
        if (panes != null) {
            for (Pane pane : panes) {
                if (pane != null) {
                    pane.getChildren().forEach(new Consumer<Node>() {
                        @Override
                        public void accept(Node node) {
                            removeAction(node);
                        }
                    });
                }
            }
        }
    }

    public static DraggedWindow applyDragged(Node node) {
        DraggedWindow draggedWindow = new DraggedWindow(node);
        draggedWindow.applyDragged();
        return draggedWindow;
    }

    public static class DraggedWindow {
        private final Node node;
        private Window window;

        private double x1;
        private double y1;
        private double x_stage;
        private double y_stage;

        public DraggedWindow(Node node) {
            this.node = node;
            this.window = node.getScene().getWindow();
        }

        private Window getWindow() {
            if (window != null) {
                return window;
            }
            window = node.getScene().getWindow();
            return window;
        }

        public void applyDragged() {
            node.setOnMouseDragged(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event) {
                    //计算
                    getWindow().setX(x_stage + event.getScreenX() - x1);
                    getWindow().setY(y_stage + event.getScreenY() - y1);
                }
            });
            node.setOnMousePressed(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event) {
                    //按下鼠标后，记录当前鼠标的坐标
                    x1 = event.getScreenX();
                    y1 = event.getScreenY();
                    x_stage = getWindow().getX();
                    y_stage = getWindow().getY();
                }
            });
        }

        public void cancelApplyDragged() {
            node.setOnMouseDragged(null);
            node.setOnMousePressed(null);
        }
    }
}
